(function () {
    
    window.countlySession = window.countlySession || {};
    CountlyHelpers.createMetricModel(window.countlySession, {name: "users", estOverrideMetric:"users"}, jQuery);
    
    countlySession.callback = function(isRefresh, data){
      if(isRefresh){
          countlyLocation.refresh(data);
      }
      else{
          countlyLocation.initialize();
      }
    };
    
    countlySession.getSessionData = function () {
        var map = {t:"total-sessions", n:"new-users", u:"total-users", d:"total-duration", e:"events", p:"paying-users", m:"messaging-users"};
        var ret = {};
        var data = countlyCommon.getDashboardData(countlySession.getDb(), ["t", "n", "u", "d", "e", "p", "m"], ["u", "p", "m"], {u:"users"}, countlySession.clearObject);
        
        for(var i in data){
            ret[map[i]] = data[i];
        }
        
        //calculate returning users
        var changeReturning = countlyCommon.getPercentChange(
            Math.max(ret["total-users"]["prev-total"] - ret["new-users"]["prev-total"], 0), 
            Math.max(ret["total-users"]["total"] - ret["new-users"]["total"], 0));
        ret["returning-users"] = {
            "total":Math.max(ret["total-users"]["total"] - ret["new-users"]["total"], 0),
            "prev-total":Math.max(ret["total-users"]["prev-total"] - ret["new-users"]["prev-total"], 0),
            "change":changeReturning.percent,
            "trend":changeReturning.trend
        };
        
        //convert duration to minutes
        ret["total-duration"]["total"] /= 60;
        ret["total-duration"]["prev-total"] /= 60;
        
        //calculate average duration
        var changeAvgDuration = countlyCommon.getPercentChange(
            (ret["total-sessions"]["prev-total"] === 0) ? 0 : ret["total-duration"]["prev-total"] / ret["total-sessions"]["prev-total"], 
            (ret["total-sessions"]["total"] === 0 ) ? 0 : ret["total-duration"]["total"] / ret["total-sessions"]["total"]);
        ret["avg-duration-per-session"] = {
            "prev-total":(ret["total-sessions"]["prev-total"] === 0) ? 0 : ret["total-duration"]["prev-total"] / ret["total-sessions"]["prev-total"],
            "total":(ret["total-sessions"]["total"] === 0 ) ? 0 : ret["total-duration"]["total"] / ret["total-sessions"]["total"],
            "change":changeAvgDuration.percent,
            "trend":changeAvgDuration.trend
        };
        
        ret["total-duration"]["total"] = countlyCommon.timeString(ret["total-duration"]["total"]);
        ret["total-duration"]["prev-total"] = countlyCommon.timeString(ret["total-duration"]["prev-total"]);
        ret["avg-duration-per-session"]["total"] = countlyCommon.timeString(ret["avg-duration-per-session"]["total"]);
        ret["avg-duration-per-session"]["prev-total"] = countlyCommon.timeString(ret["avg-duration-per-session"]["prev-total"]);
        
        //calculate average events
        var changeAvgEvents = countlyCommon.getPercentChange(
            (ret["total-users"]["prev-total"] === 0) ? 0 : ret["events"]["prev-total"] / ret["total-users"]["prev-total"], 
            (ret["total-users"]["total"] === 0 ) ? 0 : ret["events"]["total"] / ret["total-users"]["total"]);
        ret["avg-events"] = {
            "prev-total":(ret["total-users"]["prev-total"] === 0) ? 0 : ret["events"]["prev-total"] / ret["total-users"]["prev-total"],
            "total":(ret["total-users"]["total"] === 0 ) ? 0 : ret["events"]["total"] / ret["total-users"]["total"],
            "change":changeAvgEvents.percent,
            "trend":changeAvgEvents.trend
        };
        
        ret["avg-events"]["total"] = ret["avg-events"]["total"].toFixed(1);
        ret["avg-events"]["prev-total"] = ret["avg-events"]["prev-total"].toFixed(1);
        
        //get sparkleLine data
        var sparkLines = countlyCommon.getSparklineData(countlySession.getDb(), {
            "total-sessions": "t",
            "new-users": "n",
            "total-users": "u",
            "total-duration": "d",
            "events": "e",
            "returning-users": function(tmp_x){return Math.max(tmp_x["u"] - tmp_x["n"], 0);},
            "avg-duration-per-session": function(tmp_x){return (tmp_x["t"] == 0) ? 0 : (tmp_x["d"] / tmp_x["t"]);},
            "avg-events": function(tmp_x){return (tmp_x["u"] == 0) ? 0 : (tmp_x["e"] / tmp_x["u"]);}
        }, countlySession.clearObject);
        
        for(var i in sparkLines){
            ret[i].sparkline = sparkLines[i];
        }
        
        return {usage:ret};
    };

    countlySession.getSessionDP = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-sessions"] },
                { data:[], label:jQuery.i18n.map["common.table.new-sessions"] },
                { data:[], label:jQuery.i18n.map["common.table.unique-sessions"] }
            ],
            dataProps = [
                { name:"t" },
                { name:"n" },
                { name:"u" }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getSessionDPTotal = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-sessions"], color:'#DDDDDD', mode:"ghost" },
                { data:[], label:jQuery.i18n.map["common.table.total-sessions"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"pt",
                    func:function (dataObj) {
                        return dataObj["t"]
                    },
                    period:"previous"
                },
                { name:"t" }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getUserDP = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-users"] },
                { data:[], label:jQuery.i18n.map["common.table.new-users"] },
                { data:[], label:jQuery.i18n.map["common.table.returning-users"] }
            ],
            dataProps = [
                { name:"u" },
                { name:"n" },
                {
                    name:"returning",
                    func:function (dataObj) {
                        return dataObj["u"] - dataObj["n"];
                    }
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getUserDPActive = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-users"], color:'#DDDDDD', mode:"ghost" },
                { data:[], label:jQuery.i18n.map["common.table.total-users"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"pt",
                    func:function (dataObj) {
                        return dataObj["u"]
                    },
                    period:"previous"
                },
                {
                    name:"t",
                    func:function (dataObj) {
                        return dataObj["u"]
                    }
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getUserDPNew = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.new-users"], color:'#DDDDDD', mode:"ghost"},
                { data:[], label:jQuery.i18n.map["common.table.new-users"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"pn",
                    func:function (dataObj) {
                        return dataObj["n"]
                    },
                    period:"previous"
                },
                { name:"n" }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getMsgUserDPActive = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-users"], color: countlyCommon.GRAPH_COLORS[0]},
                { data:[], label:jQuery.i18n.map["common.table.messaging-users"], color:countlyCommon.GRAPH_COLORS[1] }
            ],
            dataProps = [
                {
                    name:"u"
                },
                {
                    name:"m"
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getDurationDP = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.graph.time-spent"], color:'#DDDDDD', mode:"ghost"},
                { data:[], label:jQuery.i18n.map["common.graph.time-spent"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"previous_t",
                    func:function (dataObj) {
                        return ((dataObj["d"] / 60).toFixed(1));
                    },
                    period:"previous"
                },
                {
                    name:"t",
                    func:function (dataObj) {
                        return ((dataObj["d"] / 60).toFixed(1));
                    }
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getDurationDPAvg = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.graph.average-time"], color:'#DDDDDD', mode:"ghost"},
                { data:[], label:jQuery.i18n.map["common.graph.average-time"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"previous_average",
                    func:function (dataObj) {
                        return ((dataObj["t"] == 0) ? 0 : ((dataObj["d"] / dataObj["t"]) / 60).toFixed(1));
                    },
                    period:"previous"
                },
                {
                    name:"average",
                    func:function (dataObj) {
                        return ((dataObj["t"] == 0) ? 0 : ((dataObj["d"] / dataObj["t"]) / 60).toFixed(1));
                    }
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getEventsDP = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.graph.reqs-received"], color:'#DDDDDD', mode:"ghost"},
                { data:[], label:jQuery.i18n.map["common.graph.reqs-received"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"pe",
                    func:function (dataObj) {
                        return dataObj["e"]
                    },
                    period:"previous"
                },
                {
                    name:"e"
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };

    countlySession.getEventsDPAvg = function () {

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.graph.avg-reqs-received"], color:'#DDDDDD', mode:"ghost"},
                { data:[], label:jQuery.i18n.map["common.graph.avg-reqs-received"], color:'#333933' }
            ],
            dataProps = [
                {
                    name:"previous_average",
                    func:function (dataObj) {
                        return ((dataObj["u"] == 0) ? 0 : ((dataObj["e"] / dataObj["u"]).toFixed(1)));
                    },
                    period:"previous"
                },
                {
                    name:"average",
                    func:function (dataObj) {
                        return ((dataObj["u"] == 0) ? 0 : ((dataObj["e"] / dataObj["u"]).toFixed(1)));
                    }
                }
            ];

        return countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps);
    };
    
    function durationRange(){
        var sec = jQuery.i18n.map["common.seconds"],
            min = jQuery.i18n.map["common.minutes"],
            hr = jQuery.i18n.map["common.hour"];

        return [
            "0 - 10 " + sec,
            "11 - 30 " + sec,
            "31 - 60 " + sec,
            "1 - 3 " + min,
            "3 - 10 " + min,
            "10 - 30 " + min,
            "30 - 60 " + min,
            "> 1 " + hr
        ];
    }

    countlySession.explainDurationRange = function (index) {
        return durationRange()[index];
    };

    countlySession.getDurationIndex = function (duration) {
        return durationRange().indexOf(duration);
    };
    
    function frequencyRange(){
        var localHours = jQuery.i18n.map["user-loyalty.range.hours"],
            localDay = jQuery.i18n.map["user-loyalty.range.day"],
            localDays = jQuery.i18n.map["user-loyalty.range.days"];

        return [
            jQuery.i18n.map["user-loyalty.range.first-session"],
            "1-24 " + localHours,
            "1 " + localDay,
            "2 " + localDays,
            "3 " + localDays,
            "4 " + localDays,
            "5 " + localDays,
            "6 " + localDays,
            "7 " + localDays,
            "8-14 " + localDays,
            "15-30 " + localDays,
            "30+ " + localDays
        ];
    }
    
    countlySession.explainFrequencyRange = function (index) {
        return frequencyRange()[index];
    };

    countlySession.getFrequencyIndex = function (frequency) {
        return frequencyRange().indexOf(frequency);
    };
    
    function loyaltyRange(){
        return [
            "1",
            "2",
            "3-5",
            "6-9",
            "10-19",
            "20-49",
            "50-99",
            "100-499",
            "> 500"
        ];
    }
        
    countlySession.explainLoyaltyRange = function (index) {
        return loyaltyRange()[index];
    };

    countlySession.getLoyaltyIndex = function (loyalty) {
        return loyaltyRange().indexOf(loyalty);
    };

    countlySession.getTopUserBars = function () {

        var barData = [],
            sum = 0,
            maxItems = 3,
            totalPercent = 0;

        var chartData = [
                { data:[], label:jQuery.i18n.map["common.table.total-users"] }
            ],
            dataProps = [
                {
                    name:"t",
                    func:function (dataObj) {
                        return dataObj["u"]
                    }
                }
            ];

        var totalUserData = countlyCommon.extractChartData(countlySession.getDb(), countlySession.clearObject, chartData, dataProps),
            topUsers = _.sortBy(_.reject(totalUserData.chartData, function (obj) {
                return obj["t"] == 0;
            }), function (obj) {
                return -obj["t"];
            });

        if (topUsers.length < 3) {
            maxItems = topUsers.length;
        }

        for (var i = 0; i < maxItems; i++) {
            sum += topUsers[i]["t"];
        }

        for (var i = 0; i < maxItems; i++) {
            var percent = Math.floor((topUsers[i]["t"] / sum) * 100);
            totalPercent += percent;

            if (i == (maxItems - 1)) {
                percent += 100 - totalPercent;
            }

            barData[i] = { "name":topUsers[i]["date"], "percent":percent };
        }

        return barData;
    };

    countlySession.clearObject = function (obj) {
        if (obj) {
            if (!obj["t"]) obj["t"] = 0;
            if (!obj["n"]) obj["n"] = 0;
            if (!obj["u"]) obj["u"] = 0;
            if (!obj["d"]) obj["d"] = 0;
            if (!obj["e"]) obj["e"] = 0;
            if (!obj["p"]) obj["p"] = 0;
            if (!obj["m"]) obj["m"] = 0;
        }
        else {
            obj = {"t":0, "n":0, "u":0, "d":0, "e":0, "p":0, "m":0};
        }

        return obj;
    };
    
}());
